import { isString, isNumber, isArray, isBoolean, isArrayString, isObject, isInt, isPrice, isNill, arrayAminusB, isArrayIncludes, isArrayNumber } from "../src/utils/pubFunction"
export type Validate = {
    key: string,
    type: IsType,
    max?: number,
    includes?: any[],
    ArrayString?: boolean,
    ArrayNumber?: boolean,
    min?: number,
    ArrayObject?: boolean,
    format?: 'int' | 'price',
    requred?: boolean
    object_validate?: Validate[]
}
type IsType = "string" | "array" | "boolean" | "number" | "object"
type ReturnFn = { code: number, msg?: string }

export default function validate(params: Array<Validate>, data: Record<string, any>, strict: boolean = true): ReturnFn {
    try {
        if (strict) { // 严格模式
            const requred_length = params.filter(it => it.requred)
            if (Object.keys(data).length < requred_length.length) {
                throw new Error(`对象缺少必须参数'${arrayAminusB(requred_length.map(it => it.key), Object.keys(data))}'`)
            }
            if (Object.keys(data).length > params.length) {
                throw new Error(`对象存在多余参数'${arrayAminusB(Object.keys(data), params.map(it => it.key))}'`)
            }
            if (!isArrayIncludes(params.map(it => it.key), Object.keys(data))) {
                throw new Error(`对象存在错误参数'${arrayAminusB(Object.keys(data), params.map(it => it.key))}'`)
            }
        }
        for (let i = 0, len = params.length; i < len; i++) {
            const { key, type, max, includes, ArrayString, ArrayNumber, ArrayObject, min, object_validate, requred, format } = params[i]
            const value = data[key]
            if (requred) {// 判断值是否存在
                if (isNill(value)) {
                    throw new Error(`缺少'${key}'参数`)
                }
            }
            //值不存在跳下一循环
            if (isNill(value)) continue
            // includes 存在则忽略type等其他参数
            if (isArray(includes)) {
                if (!(includes as any[]).includes(value)) throw new Error(`类型错误：'${key}'只允许[${(includes as any[]).toString()}]值`)
                continue
            }
            switch (type) {
                case "string":
                    // 字符串可选字段 max min
                    if (!isString(value)) throw new Error(`类型错误：'${key}'为string`)
                    if (isNumber(max)) {
                        if (value.length > (max as number)) throw new Error(`'${key}'字段长度不能大于${max}`)
                    }
                    if (isNumber(min)) {
                        if (value.length < (min as number)) throw new Error(`'${key}'字段长度不能小于${min}`)
                    }
                    break;
                case "number":
                    // 数值可选字段 includes isPrice isInt
                    if (!isNumber(value)) throw new Error(`类型错误：'${key}'为number`)
                    if (isNumber(min)) {
                        if (value < (min as number)) throw new Error(`'${key}'不能小于${min}`)
                    }
                    if (isNumber(max)) {
                        if (value > (max as number)) throw new Error(`'${key}'不能大于${max}`)
                    }
                    if (format === 'price') {
                        if (!isPrice(value)) throw new Error(`类型错误：'${key}'只保留小数点后两位的数值`)
                    }
                    if (format === 'int') {
                        if (!isInt(value)) throw new Error(`类型错误：'${key}'为整数数值`)
                    }
                    break;
                case "boolean":
                    if (!isBoolean(value)) throw new Error(`类型错误：'${key}'为boolean`)
                    break;
                case "array":
                    // 数组可选字段 ArrayString 是否为字符串数组 min_length 长度最小值 max_length 长度最大值  ArrayObject 是否为对象数组 object_key 对象参数
                    if (!isArray(value)) throw new Error(`类型错误：'${key}'为Array`)
                    if (ArrayString) {
                        if (!isArrayString(value)) throw new Error(`类型错误：'${key}'为string[]`)
                    }
                    if (ArrayNumber) {
                        if (!isArrayNumber(value)) throw new Error(`类型错误：'${key}'为number[]`)
                    }
                    if (isNumber(min)) {
                        if (value.length < (min as number)) throw new Error(`'${key}'字段长度不能小于${min}`)
                    }
                    if (isNumber(max)) {
                        if (value.length > (max as number)) throw new Error(`'${key}'字段长度不能大于${max}`)
                    }
                    if (ArrayObject) {
                        if (object_validate) {
                            value.forEach((val: any) => {
                                const item = validate(object_validate, val)
                                if (item.code !== 0) throw new Error(`'${key}'字段${item.msg}`)
                            });
                        }
                    }
                    break;
                case "object":
                    // 对象可选字段 object_key对象参数
                    if (!isObject(value)) throw new Error(`类型错误：'${key}'为Object`)
                    if (object_validate) {
                        const item = validate(object_validate, value)
                        if (item.code !== 0) throw new Error(`'${key}'字段${item.msg}`)
                    }
                    break;
            }
        }
        return {
            code: 0
        }
    } catch (err: any) {
        return {
            code: -1,
            msg: err.message || "未知错误"
        }
    }
}
